package ru.spb.osll.myfit.client.manager;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import ru.spb.osll.myfit.client.service.PageExecutingService;
import ru.spb.osll.myfit.client.service.PageExecutingServiceAsync;
import ru.spb.osll.myfit.client.widget.PageExecutingListener;
import ru.spb.osll.myfit.common.PageExecutingResult;
import ru.spb.osll.myfit.common.PageExecutingResult.PageExecutingState;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

public class PageExecutingManager {


    private final PageExecutingServiceAsync m_pageExecutingService = GWT
            .create(PageExecutingService.class);

    private HashMap<String, List<PageExecutingListener>> myListeners = new HashMap<String, List<PageExecutingListener>>();

    private HashMap<String, Timer> myTimers = new HashMap<String, Timer>();

    public PageExecutingManager() {

    }

    public void executeTestPage(final List<PageExecutingListener> listeners,
                                String pagePath) {
        m_pageExecutingService.executePage(pagePath,
                new AsyncCallback<PageExecutingResult>() {

                    @Override
                    public void onSuccess(PageExecutingResult pageExecutingResult) {

                        PageExecutingState currentState = pageExecutingResult.getState();

                        if (currentState == PageExecutingState.FINISH) {
                            for (PageExecutingListener listener : listeners) {
                                listener.processPageExecutingResult(pageExecutingResult);
                                listener.finish();
                            }
                            return;
                        }

                        if (currentState != PageExecutingState.FAIL) {
                            for (PageExecutingListener listener : listeners) {
                                listener.processPageExecutingResult(pageExecutingResult);
                            }

                            final String id = pageExecutingResult.getID();
                            myListeners.put(id, listeners);
                            Timer timer = new Timer() {

                                @Override
                                public void run() {
                                    processExecutingPage(id);
                                }
                            };
                            myTimers.put(id, timer);
                            timer.scheduleRepeating(1000);
                        }
                    }

                    @Override
                    public void onFailure(Throwable arg0) {

                    }
                });

    }


    public void addResultToListen(final PageExecutingResult result) {
        String id = result.getID();
        if (myTimers.get(id) == null) {
            Timer timer = new Timer() {

                @Override
                public void run() {
                    processExecutingPage(result.getID());
                }
            };
            myTimers.put(result.getID(), timer);
            timer.scheduleRepeating(1000);
        }
    }


    public void addListener(String id, PageExecutingListener listener) {
        List<PageExecutingListener> listeners = myListeners.get(id);
        if(listeners == null){
            listeners = new LinkedList<PageExecutingListener>();
        }
        listeners.add(listener);
        myListeners.put(id, listeners);
    }

    private void processExecutingPage(String id) {
        m_pageExecutingService.getExecutingResult(id,
                new AsyncCallback<PageExecutingResult>() {

                    @Override
                    public void onFailure(Throwable arg0) {

                    }

                    @Override
                    public void onSuccess(PageExecutingResult pageExecutingResult) {
                        if (pageExecutingResult != null) {
                            String id = pageExecutingResult.getID();
                            List<PageExecutingListener> listeners = myListeners.get(id);
                            if (pageExecutingResult.getState() == PageExecutingState.FINISH) {

                                myTimers.get(id).cancel();

                                for (PageExecutingListener listener : listeners) {
                                    listener.processPageExecutingResult(pageExecutingResult);
                                    listener.finish();
                                }

                            } else {
                                for (PageExecutingListener listener : listeners) {
                                    listener.processPageExecutingResult(pageExecutingResult);
                                }
                            }
                        }
                    }
                });
    }
}
